package com.h3c.nem.controller;

import com.alibaba.fastjson.JSONObject;
import com.eos.common.constant.StatusCodeEnum;
import com.eos.common.custom.BusinessException;
import com.eos.common.domain.ActiveUser;
import com.eos.common.util.Result;
import com.h3c.nem.config.TopicRabbitConfig;
import com.h3c.nem.dto.*;
import com.h3c.nem.entity.SdAllWorker;
import com.h3c.nem.entity.SdOperLog;
import com.h3c.nem.entity.SdUser;
import com.h3c.nem.enums.FileOpTypeEnum;
import com.h3c.nem.service.CommService;
import com.h3c.nem.service.ITbTeacherService;
import com.h3c.nem.utils.AppBusinessException;
import com.h3c.nem.utils.BusiEnumDefine;
import com.h3c.nem.utils.CommonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Api(tags = " Common公共接口")
@CrossOrigin
@RestController
@Slf4j
@RequestMapping(value = "/comm", produces = "application/json;charset=utf-8")
public class CommController implements InitializingBean {

    @Autowired
    CommService commService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${system.runMode}")
    private String runMode;

    @Value("${begin-check-new-worker-date}")
    private String startJoinTime;

    @Value("${busi.dialogKey}")
    private String dialogKey;

    @Autowired
    private TopicRabbitConfig topicRabbitConfig;

    @Resource
    ITbTeacherService tbTeacherService;

    private static Date startUseDate;

    @Override
    public void afterPropertiesSet() throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            startUseDate = sdf.parse(startJoinTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/hrssDataTransToNem")
    @ResponseBody
    public Result hrssDataTransToNem(Integer num) {
        commService.hrssDataTransToNem(num);
        return new Result(true, 0, "HRSS入职数据转换到Nem发起成功！");
    }

    @RequestMapping("/deleteRepeatData")
    @ResponseBody
    public Result deleteRepeatData(){
        commService.deleteRepeatData();
        return new Result(true, 0, "删除重复数据成功！");
    }


    @RequestMapping("/getCiphertext")
    @ResponseBody
    public Result getCiphertext() {
        ActiveUser activeUser = CommonUtil.userHolder.get();
        if (activeUser != null) {
            String userId = activeUser.getUserId();
            //获取当前时间并转换为所需格式
            Date currentDate = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String time = sdf.format(currentDate);

            //密文：根据域账号，dialogKey，time相加使用sha1Hex加密，以下加密方法出自commons-codec-1.7.jar
            JSONObject jsonObj = new JSONObject();
            jsonObj.put("ciphertext", DigestUtils.sha1Hex(userId + dialogKey + time));
            jsonObj.put("timeStr", time);
            return new Result(true, 0, "", jsonObj);
        } else {
            throw new BusinessException(StatusCodeEnum.UN_AUTH);
        }
    }


    @RequestMapping("/checkNewEmployeeEntranceFlag/{domainAccount}")
    @ResponseBody
    public Result checkNewEmployeeEntranceFlag(@PathVariable("domainAccount") String domainAccount) {
        try {
            boolean showFlag = false;
            SdAllWorker workerDO = commService.getWorkerIdByDomain(domainAccount);
            if (workerDO.getJoinDate() != null &&
                    !workerDO.getJoinDate().before(startUseDate)) {
                showFlag = true;
            }
            HrssDTO hrssDTO = new HrssDTO();
            hrssDTO.setUserId(workerDO.getWorkerId());
            hrssDTO.setDomainAccount(domainAccount);
            hrssDTO.setNewEmployeeFlag(showFlag);
            return new Result(true, 0, "", hrssDTO);
        } catch (Exception e) {
            HrssDTO returnObj = new HrssDTO();
            returnObj.setDomainAccount(domainAccount);
            returnObj.setUserId(domainAccount);
            return new Result(true, 0, "", returnObj);
        }
    }

    @RequestMapping("/checkManagerEntranceFlag/{domainAccount}")
    @ResponseBody
    public Result checkManagerEntranceFlag(@PathVariable("domainAccount") String domainAccount) {
        try {
            boolean showFlag = false;
            LoginUserDTO loginUserDTO = commService.getUserObjByAccountId(domainAccount);
            String userRole = loginUserDTO.getUserRole();
            if (!StringUtils.isEmpty(userRole) && (userRole.contains(String.valueOf(BusiEnumDefine.USER_ROLE_ADMIN)))
                    || userRole.contains(String.valueOf(BusiEnumDefine.USER_ROLE_DIRECT_MANAGER))
                    || userRole.contains(String.valueOf(BusiEnumDefine.USER_ROLE_BP))
                    || userRole.contains(String.valueOf(BusiEnumDefine.USER_ROLE_DEPT_CONTACTOR))
                    || userRole.contains(String.valueOf(BusiEnumDefine.USER_ROLE_DEPT_MANAGER))
                    || userRole.contains(String.valueOf(BusiEnumDefine.USER_ROLE_GBBZ))
            ) {
                showFlag = true;
            }
            HrssDTO hrssDTO = new HrssDTO();
            hrssDTO.setUserId(loginUserDTO.getUserId());
            hrssDTO.setDomainAccount(domainAccount);
            hrssDTO.setManagerFlag(showFlag);
            return new Result(true, 0, "", hrssDTO);
        } catch (Exception e) {
            HrssDTO returnObj = new HrssDTO();
            returnObj.setDomainAccount(domainAccount);
            returnObj.setUserId(domainAccount);
            return new Result(true, 0, "", returnObj);
        }
    }

    @RequestMapping("/say")
    @ResponseBody
    public Result say() {
        Message message = topicRabbitConfig.getMessage("123");
        rabbitTemplate.convertAndSend(topicRabbitConfig.getExchange(), topicRabbitConfig.getOperLogQueue(), message);
        return new Result(true, 20000, "退出系统缓存清理成功", new SdOperLog());
    }

    @RequestMapping("/clearCacheData")
    @ResponseBody
    public Result clearCacheData(HttpServletRequest request) {
        String realIP = CommonUtil.getIp(request);
        String remoteAddr = realIP + ":" + request.getRemotePort();
//        commService.saveLoginHistory(commService.getLoginUserId(), commService.getLoginUserNameWithNoException(), "退出系统", remoteAddr);
        commService.clearCacheData();
        return new Result(true, 20000, "退出系统缓存清理成功", new SdOperLog());
    }

    @RequestMapping("/clearCacheDataNew")
    @ResponseBody
    public Result clearCacheDataNew() {
        Map<String, Object> dataCacheMap = CommService.dataCacheMap;
        try {
            dataCacheMap.remove(BusiEnumDefine.DOMAIN_ACCT_PREFIX + commService.getLoginUserDTO().getAccount());
        } catch (Exception e) {
            e.printStackTrace();
            log.info("无token退出");
        }
        return new Result(true, 20000, "退出系统缓存清理成功", new SdOperLog());
    }

    @RequestMapping("/switchUser")
    @ResponseBody
    public Result switchUser(@RequestBody SdUser user) {
        commService.switchUser(user);
        return new Result(true, 20000, "临时用户转换成功", new SdOperLog());
    }

    @RequestMapping("/checkNewWorker")
    @ResponseBody
    public Result checkNewWorker(@RequestBody SdUser user) {
        String value = commService.checkNewWorker();
        return new Result(true, 20000, "新员工", value);
    }

    @ApiOperation(value = "查询Redis当前缓存值", notes = "按权限查询菜单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key", value = "redis key", required = true, dataType = "String", paramType = "query")
    })
    @RequestMapping("/getReidsValue")
    @ResponseBody
    public Result getReidsValue(@RequestParam("key") String key) {
        String value = commService.getReidsValue(key);
        return new Result(true, 20000, "查询成功", value);
    }

    /**
     * 登录时，获取域名加密值
     *
     * @return
     */
    @ApiOperation(value = "对当前系统地址加密，传给sso页面；sso解密url，sso登录后回跳到我们系统；", notes = "登录时，获取域名加密值")
    @RequestMapping(value = "/encodeUrl", method = RequestMethod.POST)
    @ResponseBody
    public Result encodeUrl(@RequestBody LoginUserDTO loginUser) throws Exception {
        return new Result(true, StatusCodeEnum.LOGIN_SUCCESS, commService.loginUrl(loginUser.getLocalUrl()));
    }

    /**
     * 重新加载缓存数据
     *
     * @return
     */
    @ApiOperation(value = "重新加载缓存数据")
    @RequestMapping(value = "/initCacheData", method = RequestMethod.POST)
    @ResponseBody
    public Result initCacheData() throws Exception {
        commService.initData();
        return new Result(true, StatusCodeEnum.NORMAL);
    }

//    /**
//     * 登录时，获取验证码
//     * @return
//     */
//    @ApiOperation(value = "sso登录成功后，前端将ticket传给后端，验证身份，并获取验证码", notes = "登录时，获取域名加密值")
//    @RequestMapping(value = "/getMobileValidCode", method = RequestMethod.POST)
//    @ResponseBody
//    public Result getMobileValidCode(@RequestBody LoginUserDTO loginUser, HttpServletRequest request) throws Exception {
//        String ticket = loginUser.getTicket();
//        if (!StringUtils.isEmpty(ticket)) {
//            LoginUserDTO loginUserDTO = commService.getMobileValidCode(ticket);
//            return new Result(true, StatusCodeEnum.NORMAL, loginUserDTO);
//        }else{
//            throw new AppBusinessException("sso-ticket不能为空");
//        }
//    }
//
//    /**
//     * 验证输入的手机验证码
//     * @return
//     */
//    @ApiOperation(value = "sso登录成功后，前端将ticket传给后端，验证身份，并获取验证码", notes = "登录时，获取域名加密值")
//    @RequestMapping(value = "/validateMobileCode", method = RequestMethod.POST)
//    @ResponseBody
//    public Result validateMobileCode(@RequestBody LoginUserDTO loginUser, HttpServletRequest request) throws Exception {
//        String domainAccount = loginUser.getAccount();
//        String inputMobileValidCode = loginUser.getMobileValidCode();
//
//        if(StringUtils.isEmpty(domainAccount) || StringUtils.isEmpty(inputMobileValidCode) ){
//            throw new AppBusinessException("域账号和手机验证码不能为空");
//        }
//        String generateMobileValidCode = commService.getReidsValue(BusiEnumDefine.REDIS_AUTH_CODE_PREFIX + domainAccount);
//        if(!StringUtils.isEmpty(generateMobileValidCode)
//                && generateMobileValidCode.equals(inputMobileValidCode)){
//            Map<String, Object> userLoginMap = commService.getToken(loginUser);
//            LoginUserDTO loginUserResult = (LoginUserDTO) userLoginMap.get("info");
//            String realIP = CommonUtil.getIp(request);
//            String remoteAddr = realIP + ":" + request.getRemotePort();
//            commService.saveLoginHistory(loginUserResult.getUserId(), loginUserResult.getUserName(), "登录系统", remoteAddr);
//            return new Result(true, StatusCodeEnum.LOGIN_SUCCESS, userLoginMap);
//        }else{
//            throw new AppBusinessException("手机验证码校验失败");
//        }
//    }


    /**
     * 登录
     *
     * @return
     */
    @ApiOperation(value = "登录获取token接口", notes = "登录获取token接口")
    @RequestMapping(value = "/token", method = RequestMethod.POST)
    @ResponseBody
    public Result getToken(@RequestBody LoginUserDTO loginUser, HttpServletRequest request) throws Exception {
        String ticket = loginUser.getTicket();
        if (!StringUtils.isEmpty(ticket)) {
            Map<String, Object> userLogin = commService.getToken(ticket);
            LoginUserDTO loginUser2 = (LoginUserDTO) userLogin.get("info");
            String realIP = CommonUtil.getIp(request);
            String remoteAddr = realIP + ":" + request.getRemotePort();
            commService.saveLoginHistory(loginUser2.getUserId(), loginUser2.getUserName(), "登录系统", remoteAddr);
            return new Result(true, StatusCodeEnum.LOGIN_SUCCESS, userLogin);
        } else {
            return new Result(true, StatusCodeEnum.LOGIN_SUCCESS, commService.loginUrl(loginUser.getLocalUrl()));
        }

    }

    /**
     * 企业微信登录
     *
     * @param map
     * @param request
     * @return com.eos.common.util.Result
     * @author z22968
     * @date 2022-06-16 16:08
     */
    @PostMapping("/token/wechat/")
    public Result getTokenByWechatCode(@RequestBody HashMap<String, String> map, HttpServletRequest request) throws Exception {
        String code = map.get("code");
        if (!StringUtils.hasText(code)) {
            throw new AppBusinessException("code不能为空");
        }
        Map<String, Object> userLogin = commService.getTokenByWechatCode(code);
        LoginUserDTO loginUser2 = (LoginUserDTO) userLogin.get("info");
        String realIP = CommonUtil.getIp(request);
        String remoteAddr = realIP + ":" + request.getRemotePort();
        commService.saveLoginHistory(loginUser2.getUserId(), loginUser2.getUserName(), "登录系统", remoteAddr);
        return new Result(true, StatusCodeEnum.LOGIN_SUCCESS, userLogin);
    }

    @ApiOperation(value = "查询登录人信息接口", notes = "首页getMenu已经返回了这个结构")
    @RequestMapping("/queryLoginUserInfo")
    @ResponseBody
    public Result queryLoginUserInfo() {
        LoginUserDTO loginUserDTO = commService.queryLoginUserInfo();
        return new Result(true, 2000, "", loginUserDTO);
    }


    @PostMapping(value = "/downloadTest")
    @ResponseBody
    public Map<String, String> downloadTest() {
        try {
            File downLoadFile = commService.downloadTest();
            FileInputStream inputStream = new FileInputStream(downLoadFile);
            byte[] buffer = new byte[(int) downLoadFile.length()];
            inputStream.read(buffer);
            inputStream.close();
            Map<String, String> result = new HashMap<>();
            result.put("file", Base64Utils.encodeToString(buffer));
            result.put("filename", downLoadFile.getName());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppBusinessException("文件下载异常");
        }
    }

    @PostMapping(value = "/parseFile")
    @ResponseBody
    public String parseFile(@RequestParam("file") MultipartFile file,
                            @RequestParam("templateCode") String templateCode) {
        try {
            return commService.parseExcelByTemplate(templateCode, file);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppBusinessException("文件解析异常");
        }
    }

    @PostMapping(value = "/sendSms")
    @ResponseBody
    public String sendSms(@RequestParam("targetPhone") String targetPhone,
                          @RequestParam("smsContent") String smsContent) {
        try {
            commService.sendSmsForTest(targetPhone, smsContent);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppBusinessException("文件解析异常");
        }
        return "短信发送成功";
    }

    @PostMapping(value = "/previewUploadFile")
    @ResponseBody
    public Result previewUploadFile(@RequestParam("fileId") String fileId,
                                    @RequestParam("busiId") String busiId,
                                    @RequestParam("busiType") Integer busiType) {
        Map<String, String> previewFile = null;
        if (!StringUtils.isEmpty(fileId)) {
            previewFile = commService.previewFile(fileId);
        } else {
            previewFile = commService.previewFile(busiId, busiType);
        }
        return new Result(true, StatusCodeEnum.NORMAL, previewFile);
    }

    /**
     * 文件上傳返回上傳的文件id
     *
     * @return
     */
    @PostMapping("uploadFile")
    public Result uploadFile(@RequestParam("uploadFile") MultipartFile uploadFile,
                             @RequestParam("busiType") Integer busiType,
                             @RequestParam(value = "busiId", required = false) String busiId) {
        File file = null;
        try {
            file = new File("" + uploadFile.getOriginalFilename());
            FileUtils.copyInputStreamToFile(uploadFile.getInputStream(), file);
            String s = commService.uploadFileToSfs(busiType, file, busiId);
            commService.recordFileOperationLog(uploadFile.getOriginalFilename(), uploadFile.getSize(), FileOpTypeEnum.IMPORT);
            file.delete();
            return new Result(true, StatusCodeEnum.NORMAL, s);
        } catch (Exception e) {
            throw new AppBusinessException("上传文件失败");
        } finally {
            if (file != null) {
                file.delete();
            }
        }
    }

    @GetMapping("/deleteRedisKey")
    public Result deleteRedisKey(String key) {
        commService.deleteRedisKey(key);
        return new Result(true, StatusCodeEnum.NORMAL);
    }


    @GetMapping("/deleteSfsFile")
    public Result deleteSfsFile(String fileId) {
        commService.deleteSfsFile(fileId);
        return new Result(true, StatusCodeEnum.NORMAL);
    }

    @RequestMapping("/getPortrait/{workerId}")
    public void syncPortrait(@PathVariable("workerId") String workerId, HttpServletRequest request, HttpServletResponse response) throws Exception {


        LinkedHashMap portrait = commService.getPortrait(workerId);
        BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(portrait.get("com_img").toString())));
        BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
        response.setHeader("Content-Type", "image/jpeg");
        byte b[] = new byte[1024];
        int read;
        try {
            while ((read = bis.read(b)) != -1) {
                bos.write(b, 0, read);
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            if (bos != null) {
                bos.close();
            }
            if (bis != null) {
                bis.close();
            }
        }
    }

    @RequestMapping(value = "/getOuterAppToken", method = RequestMethod.POST)
    @ResponseBody
    public Result getOuterAppToken(@RequestBody OutAppKeyDTO outerAppKey) throws BusinessException {
        OuterAppTokenDTO outerAppToken = commService.getOuterAppToken(outerAppKey.getOuterAppKey(), outerAppKey.getOuterAppPwd());
        return new Result(true, StatusCodeEnum.NORMAL, outerAppToken);

    }

    @RequestMapping(value = "/getSdUserRoleList", method = RequestMethod.POST)
    @ResponseBody
    public Result getSdUserRoleList(@RequestHeader("Authorization") String bearerToken) {
        List<SdUserRoleDTO> sdUserRoleList = commService.getSdUserRoleList(bearerToken);
        return new Result(true, StatusCodeEnum.NORMAL, sdUserRoleList);

    }

    @RequestMapping(value = "/getUserRoleList", method = RequestMethod.POST)
    @ResponseBody
    public Result getUserRoleList() {
        List<SdUserRoleDTO> roleList = commService.getSdUserRoleList();
        return new Result(true, StatusCodeEnum.NORMAL, roleList);
    }

    @ApiOperation(value = "手机号登录生成验证码", notes = "登录时，获取手机号验证码")
    @GetMapping(value = "/getMobileValidCodeByPhone")
    public Result getMobileValidCodeByPhone(@RequestParam String phoneNum) throws BusinessException {
        if (!StringUtils.isEmpty(phoneNum)) {
            try {
                commService.getMobileValidCodeByPhone(phoneNum);
            } catch (BusinessException e) {
                return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), e.getMessage());
            }
            return new Result(true, StatusCodeEnum.NORMAL);
        } else {
            return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), "手机号为空");
        }
    }

    @ApiOperation(value = "手机号登录")
    @GetMapping(value = "/getTokenByMobile")
    public Result getTokenByMobile(@RequestParam String phoneNo,
                                   @RequestParam String code) throws BusinessException {
        if (StringUtils.hasText(phoneNo) && StringUtils.hasText(code)) {
            try {
                return new Result(true, StatusCodeEnum.NORMAL, commService.getTokenByMobile(phoneNo, code));
            } catch (Exception e) {
                return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), e.getMessage());
            }
        }
        return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), "参数缺失");
    }

    @ApiOperation(value = "账号密码登录")
    @GetMapping(value = "/getTokenByCertNo")
    public Result getTokenByCertNo(@RequestParam String certNo,
                                   @RequestParam String password) throws BusinessException {
        if (StringUtils.hasText(certNo) && StringUtils.hasText(password)) {
            try {
                return new Result(true, StatusCodeEnum.NORMAL, commService.getTokenByCertNo(certNo, password));
            } catch (AppBusinessException e) {
                return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                log.error(e.getMessage());
                return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), "登录失败");
            }
        }
        return new Result(false, StatusCodeEnum.UNKNOW_ERROR.getCode(), "参数缺失");
    }

    /**
     * 同步满足初次认证导师资格条件的员工
     * @return
     */
    @PostMapping("/syncData")
    public Result syncData(){
        tbTeacherService.autoInfoLeaderToCertificate();
        return new Result(true, StatusCodeEnum.NORMAL);
    }

}
